<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>主项目 - 嵌入组件示例</title>
    <!-- 引入Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 引入Font Awesome -->
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    
    <!-- 配置Tailwind自定义颜色和字体 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#1E40AF',
                        secondary: '#6366F1',
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    
    <!-- 自定义工具类 -->
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .transition-all-300 {
                transition: all 300ms ease-in-out;
            }
        }
    </style>
</head>
<body class="font-inter bg-gray-50 text-gray-800 min-h-screen transition-all-300">
    <div class="max-w-6xl mx-auto px-4 py-8">
        <!-- 页面标题 -->
        <header class="mb-8 text-center">
            <h1 class="text-[clamp(1.8rem,4vw,2.5rem)] font-bold text-primary mb-2">主项目应用</h1>
            <p class="text-gray-600 max-w-2xl mx-auto">这个页面展示了如何嵌入外部组件并与之进行安全通信</p>
        </header>
        
        <!-- 控制区 -->
        <div class="bg-white rounded-lg shadow-md p-6 mb-8">
            <h2 class="text-xl font-semibold mb-4 flex items-center">
                <i class="fa fa-sliders text-secondary mr-2"></i>组件控制
            </h2>
            
            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
                <!-- 发送消息区域 -->
                <div>
                    <h3 class="font-medium mb-3 text-gray-700">向嵌入组件发送消息</h3>
                    <div class="flex gap-3">
                        <input 
                            type="text" 
                            id="main-message-input" 
                            placeholder="输入要发送给嵌入组件的消息..." 
                            class="flex-1 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-secondary/50"
                        >
                        <button 
                            id="main-send-button" 
                            class="bg-secondary hover:bg-secondary/90 text-white px-4 py-2 rounded-md transition-all-300 flex items-center"
                            disabled
                        >
                            <i class="fa fa-paper-plane mr-2"></i>发送
                        </button>
                    </div>
                </div>
                
                <!-- 组件尺寸控制 -->
                <div>
                    <h3 class="font-medium mb-3 text-gray-700">调整组件尺寸</h3>
                    <div class="flex flex-wrap gap-3">
                        <button data-size="small" class="px-3 py-1 border border-gray-300 rounded-md hover:bg-gray-100 transition-all-300">
                            小 (600x400)
                        </button>
                        <button data-size="medium" class="px-3 py-1 border border-gray-300 rounded-md hover:bg-gray-100 transition-all-300">
                            中 (800x600)
                        </button>
                        <button data-size="large" class="px-3 py-1 border border-gray-300 rounded-md hover:bg-gray-100 transition-all-300">
                            大 (1000x800)
                        </button>
                        <button data-size="full" class="px-3 py-1 border border-gray-300 rounded-md hover:bg-gray-100 transition-all-300">
                            全屏
                        </button>
                    </div>
                </div>
            </div>
        </div>
        
        <!-- 嵌入组件区域 -->
        <div class="mb-8">
            <div class="flex justify-between items-center mb-4">
                <h2 class="text-xl font-semibold flex items-center">
                    <i class="fa fa-puzzle-piece text-secondary mr-2"></i>嵌入组件
                </h2>
                <div id="embed-status" class="flex items-center text-sm px-3 py-1 rounded-full bg-yellow-100 text-yellow-800">
                    <span class="w-2 h-2 rounded-full bg-yellow-500 mr-2 inline-block"></span>
                    <span>等待组件加载...</span>
                </div>
            </div>
            
            <!-- 嵌入组件的容器 -->
            <div id="embed-container" class="relative bg-gray-100 rounded-lg shadow-md overflow-hidden">
                <!-- 加载状态指示器 -->
                <div id="loading-indicator" class="absolute inset-0 flex items-center justify-center bg-white bg-opacity-80 z-10">
                    <div class="flex flex-col items-center">
                        <div class="w-12 h-12 border-4 border-secondary border-t-transparent rounded-full animate-spin mb-3"></div>
                        <p class="text-gray-600">加载组件中...</p>
                    </div>
                </div>
                
                <!-- iframe将在这里动态添加 -->
            </div>
        </div>
        
        <!-- 通信日志区域 -->
        <div>
            <h2 class="text-xl font-semibold mb-4 flex items-center">
                <i class="fa fa-history text-secondary mr-2"></i>通信日志
            </h2>
            
            <div id="main-message-log" class="bg-white rounded-lg shadow-md p-4 h-64 overflow-y-auto border border-gray-200">
                <p class="text-gray-500 text-sm italic">通信日志将显示在这里...</p>
            </div>
        </div>
        
        <!-- 通知区域 -->
        <div id="notification-area" class="fixed bottom-4 right-4 z-50 flex flex-col gap-3 max-w-xs"></div>
    </div>

    <script>
        // 配置 - 允许的嵌入组件域名，增强安全性
        const ALLOWED_EMBED_ORIGINS = [
            'http://localhost:8080',
            'https://your-embedded-component-domain.com'
        ];
        
        // 消息类型常量，与嵌入组件保持一致
        const MESSAGE_TYPES = {
            // 从嵌入页面发送到主项目
            SEND_MESSAGE: 'EMBEDDED:SEND_MESSAGE',
            REQUEST_SIZE_CHANGE: 'EMBEDDED:REQUEST_SIZE_CHANGE',
            NOTIFY: 'EMBEDDED:NOTIFY',
            COLOR_CHANGE: 'EMBEDDED:COLOR_CHANGE',
            READY: 'EMBEDDED:READY',
            
            // 从主项目发送到嵌入页面
            RECEIVE_MESSAGE: 'MAIN:SEND_MESSAGE',
            SIZE_CHANGED: 'MAIN:SIZE_CHANGED',
            ACKNOWLEDGE: 'MAIN:ACKNOWLEDGE'
        };
        
        // DOM元素
        const elements = {
            messageInput: document.getElementById('main-message-input'),
            sendButton: document.getElementById('main-send-button'),
            messageLog: document.getElementById('main-message-log'),
            embedContainer: document.getElementById('embed-container'),
            embedStatus: document.getElementById('embed-status'),
            loadingIndicator: document.getElementById('loading-indicator'),
            sizeButtons: document.querySelectorAll('[data-size]'),
            notificationArea: document.getElementById('notification-area')
        };
        
        // 状态管理
        const state = {
            embedLoaded: false,
            embedOrigin: null,
            iframe: null,
            logMessages: []
        };
        
        // 初始化
        function init() {
            // 创建并加载iframe
            createIframe();
            
            // 设置事件监听器
            setupEventListeners();
        }
        
        // 创建iframe元素
        function createIframe() {
            // 创建iframe元素
            const iframe = document.createElement('iframe');
            
            // 设置iframe属性
            iframe.src = 'embedded-page.html'; // 嵌入组件的URL
            iframe.width = '100%';
            iframe.height = '600px';
            iframe.className = 'w-full border-none';
            iframe.title = '嵌入式交互组件';
            iframe.allow = 'clipboard-write'; // 根据需要添加权限
            
            // 保存iframe引用
            state.iframe = iframe;
            
            // 添加到容器
            elements.embedContainer.appendChild(iframe);
            
            // 监听iframe加载完成事件
            iframe.onload = () => {
                logMessage('嵌入组件加载完成', 'info');
            };
        }
        
        // 设置事件监听器
        function setupEventListeners() {
            // 监听来自嵌入组件的消息
            window.addEventListener('message', handleEmbedMessage);
            
            // 发送消息按钮点击事件
            elements.sendButton.addEventListener('click', sendMessageToEmbed);
            
            // 输入框回车发送消息
            elements.messageInput.addEventListener('keypress', (e) => {
                if (e.key === 'Enter') {
                    sendMessageToEmbed();
                }
            });
            
            // 尺寸按钮点击事件
            elements.sizeButtons.forEach(button => {
                button.addEventListener('click', () => {
                    const size = button.getAttribute('data-size');
                    resizeEmbed(size);
                });
            });
        }
        
        // 处理来自嵌入组件的消息
        function handleEmbedMessage(event) {
            // 验证消息来源
            if (!isAllowedEmbedOrigin(event.origin)) {
                logMessage(`拒绝来自未授权域名的消息: ${event.origin}`, 'error');
                return;
            }
            
            // 记录嵌入组件域名，用于后续通信
            if (!state.embedOrigin) {
                state.embedOrigin = event.origin;
            }
            
            // 验证消息格式
            if (!event.data || !event.data.type) {
                logMessage('收到格式不正确的消息', 'error');
                return;
            }
            
            // 处理不同类型的消息
            switch (event.data.type) {
                case MESSAGE_TYPES.READY:
                    // 嵌入组件准备就绪
                    state.embedLoaded = true;
                    updateEmbedStatus(true);
                    logMessage(`嵌入组件已准备就绪 (版本: ${event.data.payload.version})`, 'info');
                    
                    // 启用发送按钮
                    elements.sendButton.disabled = false;
                    elements.sendButton.classList.remove('opacity-50', 'cursor-not-allowed');
                    
                    // 隐藏加载指示器
                    elements.loadingIndicator.classList.add('hidden');
                    
                    // 发送初始欢迎消息
                    sendMessageToEmbed('欢迎连接到主项目！');
                    break;
                    
                case MESSAGE_TYPES.SEND_MESSAGE:
                    logMessage(`收到组件消息: ${event.data.payload}`, 'receive');
                    // 发送确认收到消息
                    sendAcknowledge(event.data.id);
                    break;
                    
                case MESSAGE_TYPES.NOTIFY:
                    logMessage(`收到组件通知: ${event.data.payload}`, 'notify');
                    // 显示通知给用户
                    showNotification(event.data.payload);
                    // 发送确认收到消息
                    sendAcknowledge(event.data.id);
                    break;
                    
                case MESSAGE_TYPES.COLOR_CHANGE:
                    logMessage(`组件请求更改颜色为: ${event.data.payload}`, 'info');
                    // 更改主项目背景颜色
                    document.body.style.backgroundColor = getColorValue(event.data.payload);
                    // 发送确认收到消息
                    sendAcknowledge(event.data.id);
                    break;
                    
                case MESSAGE_TYPES.REQUEST_SIZE_CHANGE:
                    logMessage(`组件请求调整尺寸: ${event.data.payload.width}x${event.data.payload.height}`, 'info');
                    // 可以根据需要调整iframe尺寸
                    state.iframe.width = event.data.payload.width;
                    state.iframe.height = event.data.payload.height;
                    // 通知组件尺寸已更改
                    sendSizeChanged(event.data.payload.width, event.data.payload.height);
                    // 发送确认收到消息
                    sendAcknowledge(event.data.id);
                    break;
                    
                default:
                    logMessage(`收到未知类型的消息: ${event.data.type}`, 'warning');
            }
        }
        
        // 向嵌入组件发送消息
        function sendMessageToEmbed(message = null) {
            // 如果没有提供消息，从输入框获取
            const messageText = typeof message === 'string' ? message : elements.messageInput.value.trim();
            if (!messageText) return;
            
            if (!state.embedLoaded || !state.iframe) {
                logMessage('嵌入组件尚未加载完成，无法发送消息', 'error');
                return;
            }
            
            const messageId = generateMessageId();
            const payload = {
                id: messageId,
                type: MESSAGE_TYPES.RECEIVE_MESSAGE,
                payload: messageText,
                // timestamp: new Date().toISOString()
            };
            
            // 发送消息
            state.iframe.contentWindow.postMessage(payload, state.embedOrigin);
            logMessage(`发送消息到组件: ${messageText}`, 'send');
            
            // 如果是用户输入的消息，清空输入框
            if (!message) {
                elements.messageInput.value = '';
            }
        }
        
        // 调整嵌入组件尺寸
        function resizeEmbed(size) {
            if (!state.embedLoaded || !state.iframe) {
                logMessage('嵌入组件尚未加载完成，无法调整尺寸', 'error');
                return;
            }
            
            let width, height;
            
            switch (size) {
                case 'small':
                    width = '600px';
                    height = '400px';
                    break;
                case 'medium':
                    width = '800px';
                    height = '600px';
                    break;
                case 'large':
                    width = '1000px';
                    height = '800px';
                    break;
                case 'full':
                    width = '100%';
                    height = '80vh';
                    break;
                default:
                    return;
            }
            
            // 设置iframe尺寸
            state.iframe.style.width = width;
            state.iframe.style.height = height;
            
            // 通知组件尺寸已更改
            sendSizeChanged(width, height);
            
            logMessage(`已调整组件尺寸为: ${width} x ${height}`, 'info');
        }
        
        // 发送尺寸已更改的通知
        function sendSizeChanged(width, height) {
            if (!state.embedLoaded || !state.iframe) return;
            
            const messageId = generateMessageId();
            const payload = {
                id: messageId,
                type: MESSAGE_TYPES.SIZE_CHANGED,
                payload: {
                    width,
                    height
                },
                timestamp: new Date().toISOString()
            };
            
            state.iframe.contentWindow.postMessage(payload, state.embedOrigin);
        }
        
        // 发送确认收到消息
        function sendAcknowledge(messageId) {
            if (!state.embedLoaded || !state.iframe) return;
            
            const payload = {
                id: generateMessageId(),
                type: MESSAGE_TYPES.ACKNOWLEDGE,
                payload: {
                    acknowledgedId: messageId
                },
                timestamp: new Date().toISOString()
            };
            
            state.iframe.contentWindow.postMessage(payload, state.embedOrigin);
        }
        
        // 显示通知
        function showNotification(message) {
            const notification = document.createElement('div');
            notification.className = 'bg-white border-l-4 border-secondary shadow-lg p-4 transform transition-all duration-300 translate-x-full opacity-0';
            notification.innerHTML = `
                <div class="flex">
                    <div class="flex-shrink-0">
                        <i class="fa fa-bell text-secondary"></i>
                    </div>
                    <div class="ml-3">
                        <p class="text-sm text-gray-700">${message}</p>
                    </div>
                    <button class="ml-auto flex-shrink-0 text-gray-400 hover:text-gray-500">
                        <i class="fa fa-times"></i>
                    </button>
                </div>
            `;
            
            // 添加到通知区域
            elements.notificationArea.appendChild(notification);
            
            // 触发动画
            setTimeout(() => {
                notification.classList.remove('translate-x-full', 'opacity-0');
            }, 10);
            
            // 关闭按钮事件
            notification.querySelector('button').addEventListener('click', () => {
                removeNotification(notification);
            });
            
            // 自动关闭
            setTimeout(() => {
                removeNotification(notification);
            }, 5000);
        }
        
        // 移除通知
        function removeNotification(notification) {
            notification.classList.add('translate-x-full', 'opacity-0');
            setTimeout(() => {
                notification.remove();
            }, 300);
        }
        
        // 记录消息到日志
        function logMessage(message, type = 'info') {
            // 保存到日志数组
            state.logMessages.push({
                message,
                type,
                timestamp: new Date()
            });
            
            // 限制日志长度
            if (state.logMessages.length > 50) {
                state.logMessages.shift();
            }
            
            // 更新UI
            renderMessageLog();
        }
        
        // 渲染消息日志
        function renderMessageLog() {
            elements.messageLog.innerHTML = '';
            
            if (state.logMessages.length === 0) {
                elements.messageLog.innerHTML = '<p class="text-gray-500 text-sm italic">通信日志将显示在这里...</p>';
                return;
            }
            
            state.logMessages.forEach(entry => {
                const logItem = document.createElement('div');
                logItem.className = 'mb-2 pb-2 border-b border-gray-100 last:border-0 last:mb-0 last:pb-0';
                
                const timeSpan = document.createElement('span');
                timeSpan.className = 'text-xs text-gray-400 mr-2';
                timeSpan.textContent = entry.timestamp.toLocaleTimeString();
                
                const messageSpan = document.createElement('span');
                
                // 根据消息类型设置样式
                switch (entry.type) {
                    case 'send':
                        messageSpan.className = 'text-blue-600';
                        messageSpan.innerHTML = `<i class="fa fa-arrow-down text-xs mr-1"></i> ${entry.message}`;
                        break;
                    case 'receive':
                        messageSpan.className = 'text-green-600';
                        messageSpan.innerHTML = `<i class="fa fa-arrow-up text-xs mr-1"></i> ${entry.message}`;
                        break;
                    case 'error':
                        messageSpan.className = 'text-red-600';
                        messageSpan.innerHTML = `<i class="fa fa-exclamation-circle text-xs mr-1"></i> ${entry.message}`;
                        break;
                    case 'warning':
                        messageSpan.className = 'text-yellow-600';
                        messageSpan.innerHTML = `<i class="fa fa-exclamation-triangle text-xs mr-1"></i> ${entry.message}`;
                        break;
                    case 'notify':
                        messageSpan.className = 'text-purple-600';
                        messageSpan.innerHTML = `<i class="fa fa-bell text-xs mr-1"></i> ${entry.message}`;
                        break;
                    default:
                        messageSpan.className = 'text-gray-700';
                        messageSpan.innerHTML = `<i class="fa fa-info-circle text-xs mr-1"></i> ${entry.message}`;
                }
                
                logItem.appendChild(timeSpan);
                logItem.appendChild(messageSpan);
                elements.messageLog.appendChild(logItem);
            });
            
            // 滚动到底部
            elements.messageLog.scrollTop = elements.messageLog.scrollHeight;
        }
        
        // 更新嵌入组件状态显示
        function updateEmbedStatus(connected) {
            if (connected) {
                elements.embedStatus.className = 'flex items-center text-sm px-3 py-1 rounded-full bg-green-100 text-green-800';
                elements.embedStatus.innerHTML = '<span class="w-2 h-2 rounded-full bg-green-500 mr-2 inline-block"></span><span>已连接到组件</span>';
            } else {
                elements.embedStatus.className = 'flex items-center text-sm px-3 py-1 rounded-full bg-red-100 text-red-800';
                elements.embedStatus.innerHTML = '<span class="w-2 h-2 rounded-full bg-red-500 mr-2 inline-block"></span><span>与组件断开连接</span>';
            }
        }
        
        // 验证嵌入组件来源是否被允许
        function isAllowedEmbedOrigin(origin) {
            // 开发环境下允许所有来源（方便测试）
            // if (process.env.NODE_ENV === 'development') {
            //     return true;
            // }
            return true;
            // return ALLOWED_EMBED_ORIGINS.includes(origin);
        }
        
        // 生成颜色值
        function getColorValue(colorName) {
            const colors = {
                red: '#fee2e2',
                green: '#dcfce7',
                blue: '#dbeafe',
                purple: '#f3e8ff'
            };
            
            return colors[colorName] || '#f3f4f6';
        }
        
        // 生成唯一消息ID
        function generateMessageId() {
            return Date.now().toString(36) + Math.random().toString(36).substr(2, 5);
        }
        
        // 初始化应用
        document.addEventListener('DOMContentLoaded', init);
    </script>
</body>
</html>
